home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / progtool / modula2 / pl0 / pl0parse.mod < prev    next >
Encoding:
Modula Implementation  |  1994-09-22  |  8.8 KB  |  492 lines

  1.  
  2. IMPLEMENTATION MODULE PL0Parser;
  3.  
  4. FROM SYSTEM IMPORT TSIZE;
  5.  
  6. FROM Storage IMPORT ALLOCATE, CreateHeap;
  7.  
  8. FROM TextWindows IMPORT Window, OpenTextWindow, Write, WriteLn,
  9.                         WriteCard, WriteString, Invert, CloseTextWindow;
  10.                         
  11. FROM Windows IMPORT WindowElements, Title;
  12.  
  13. FROM PL0Scanner IMPORT Symbol, sym, id, num, Diff, KeepId, GetSym, Mark;
  14.  
  15. FROM PL0Generator IMPORT Label, Gen, fixup;
  16.  
  17.  
  18. TYPE 
  19.   ObjectClass = (Const, Var, Proc, Header);
  20.   ObjPtr = POINTER TO Object;
  21.   Object = RECORD
  22.              name : CARDINAL;
  23.              next : ObjPtr;
  24.              CASE kind : ObjectClass OF
  25.                Const  : val : INTEGER;                  |
  26.                Var    : vlev, vadr : CARDINAL;          |
  27.                Proc   : plev, padr, size : CARDINAL;    |
  28.                Header : last, down : ObjPtr;            |
  29.              END;
  30.            END;  
  31.  
  32.  
  33. VAR
  34.   topScope, bottom, undef : ObjPtr;
  35.   curlev : CARDINAL;
  36.   win : Window;
  37.   
  38.  
  39. PROCEDURE err(n : CARDINAL);
  40. BEGIN
  41.   noerr := FALSE;
  42.   Mark(n);
  43.   Invert(win,TRUE);
  44.   WriteCard(win,n,1);
  45.   Invert(win,FALSE);
  46. END err;
  47.  
  48.  
  49. PROCEDURE test(s : Symbol; n : CARDINAL);
  50. BEGIN
  51.   IF sym<s THEN
  52.      err(n);
  53.      REPEAT
  54.        GetSym;
  55.      UNTIL sym>=s;
  56.   END;
  57. END test;
  58.  
  59.  
  60. (*  - neues Objekt einrichten
  61.     - Fehlermeldung ausgeben, falls bereits ein Objekt mit diesem
  62.       Namen definiert ist *)
  63.  
  64. PROCEDURE NewObj(k : ObjectClass) : ObjPtr;
  65. VAR
  66.   obj : ObjPtr;
  67.   
  68. BEGIN
  69.   obj := topScope^.next;
  70.   WHILE obj # NIL DO
  71.     IF Diff(id,obj^.name)=0 THEN
  72.        err(25);
  73.     END;
  74.     obj := obj^.next;
  75.   END;
  76.   
  77.   ALLOCATE(obj,TSIZE(Object));
  78.   WITH obj^ DO
  79.     name := id;
  80.     kind := k;
  81.     next := NIL;
  82.   END; (* WITH *)
  83.   
  84.   KeepId;
  85.   topScope^.last^.next := obj;
  86.   topScope^.last := obj;
  87.   RETURN obj;
  88. END NewObj;
  89.  
  90.  
  91. PROCEDURE find(id : CARDINAL) : ObjPtr;
  92. VAR
  93.   hd, obj : ObjPtr;
  94.   
  95. BEGIN
  96.   hd := topScope;
  97.   WHILE hd # NIL DO
  98.     obj := hd^.next;
  99.     WHILE obj # NIL DO
  100.       IF Diff(id,obj^.name)=0 THEN
  101.          RETURN obj;
  102.       ELSE
  103.          obj := obj^.next;
  104.       END;
  105.     END;
  106.     hd := hd^.down;
  107.   END;
  108.   err(11);
  109.   RETURN undef;
  110. END find;
  111.  
  112.  
  113. PROCEDURE expression;
  114. VAR
  115.   addop : Symbol;
  116.   
  117.   
  118.   PROCEDURE factor;
  119.   VAR
  120.     obj : ObjPtr;
  121.     
  122.   BEGIN
  123.     WriteString(win,"factor");
  124.     WriteLn(win);
  125.     test(lparen,6);
  126.     IF sym=ident THEN
  127.        obj := find(id);
  128.        WITH obj^ DO
  129.          CASE kind OF
  130.            Const : Gen(0,0,val);                |
  131.            Var   : Gen(2,curlev-vlev,vadr);     |
  132.            Proc  : err(21);                     |
  133.          END;
  134.        END; (* WITH *)
  135.        GetSym;
  136.     ELSIF sym=number THEN
  137.        Gen(0,0,num);
  138.        GetSym;
  139.     ELSIF sym=lparen THEN
  140.        GetSym;
  141.        expression;
  142.        IF sym=rparen THEN
  143.           GetSym;
  144.        ELSE
  145.           err(7);
  146.        END;
  147.     ELSE
  148.        err(8);
  149.     END;
  150.   END factor;
  151.   
  152.  
  153.   PROCEDURE term;
  154.   VAR
  155.     mulop : Symbol;
  156.     
  157.   BEGIN
  158.     WriteString(win,"term");
  159.     WriteLn(win);
  160.     factor;
  161.     WHILE (times<=sym) AND (sym<=div) DO
  162.       mulop := sym;
  163.       GetSym;
  164.       factor;
  165.       IF mulop=times THEN
  166.          Gen(1,0,4);
  167.       ELSE
  168.          Gen(1,0,5);
  169.       END;
  170.     END;
  171.   END term;
  172.   
  173. BEGIN
  174.   WriteString(win,"expression");
  175.   WriteLn(win);
  176.   IF (plus<=sym) AND (sym<=minus) THEN
  177.      addop := sym;
  178.      GetSym;
  179.      term;
  180.      IF addop=minus THEN
  181.         Gen(1,0,1);
  182.      END;
  183.   ELSE
  184.      term; 
  185.   END;
  186.   
  187.   WHILE (plus<=sym) AND (sym<=minus) DO
  188.     addop := sym;
  189.     GetSym;
  190.     term;
  191.     IF addop=plus THEN
  192.        Gen(1,0,2);
  193.     ELSE
  194.        Gen(1,0,3);
  195.     END;
  196.   END;
  197. END expression;
  198.  
  199.  
  200. PROCEDURE condition;
  201. VAR
  202.   relop : Symbol;
  203.   
  204. BEGIN
  205.   WriteString(win,"condition");
  206.   WriteLn(win);
  207.   IF sym=odd THEN
  208.      GetSym;
  209.      expression;
  210.      Gen(1,0,6);
  211.   ELSE
  212.      expression;
  213.      IF (eql<=sym) AND (sym<=geq) THEN
  214.         relop := sym;
  215.         GetSym;
  216.         expression;
  217.         CASE relop OF
  218.           eql : Gen(1,0,8);     |
  219.           neq : Gen(1,0,9);     |
  220.           lss : Gen(1,0,10);    |
  221.           geq : Gen(1,0,11);    |
  222.           gtr : Gen(1,0,12);    |
  223.           leq : Gen(1,0,13);    |
  224.         END;
  225.      ELSE
  226.         err(20);
  227.      END;
  228.   END;
  229. END condition;
  230.  
  231.  
  232. PROCEDURE statement;
  233. VAR
  234.   obj : ObjPtr;
  235.   L0, L1 : CARDINAL;
  236.   
  237. BEGIN
  238.   WriteString(win,"statement");
  239.   WriteLn(win);
  240.   test(ident,10);
  241.   IF sym=ident THEN
  242.      obj := find(id);
  243.      IF obj^.kind # Var THEN
  244.         err(12);
  245.         obj := NIL;
  246.      END;
  247.      GetSym;
  248.      IF sym=becomes THEN
  249.         GetSym;
  250.      ELSIF sym=eql THEN 
  251.         err(13);
  252.         GetSym;
  253.      ELSE
  254.         err(13);
  255.      END;
  256.      expression;
  257.      IF obj # NIL THEN
  258.         Gen(3,curlev-obj^.vlev,obj^.vadr);
  259.      END;
  260.   ELSIF sym=call THEN
  261.      GetSym;
  262.      IF sym=ident THEN
  263.         obj := find(id);
  264.         IF obj^.kind=Proc THEN
  265.            Gen(4,curlev-obj^.plev,obj^.padr);
  266.         ELSE
  267.            err(15);
  268.         END;
  269.         GetSym;
  270.      ELSE 
  271.         err(14);
  272.      END;
  273.   ELSIF sym=begin THEN
  274.      LOOP
  275.        statement;
  276.        IF sym=semicolon THEN
  277.           GetSym;
  278.        ELSIF sym=end THEN
  279.           GetSym;
  280.           EXIT;
  281.        ELSIF sym<const THEN
  282.           err(17);
  283.        ELSE
  284.           err(17);
  285.           EXIT;
  286.        END;
  287.      END;
  288.   ELSIF sym=if THEN
  289.      GetSym;
  290.      condition;
  291.      IF sym=then THEN 
  292.         GetSym;
  293.      ELSE
  294.         err(16);
  295.      END;
  296.      L0 := Label();
  297.      Gen(7,0,0);
  298.      statement;
  299.      fixup(L0);
  300.   ELSIF sym=while THEN
  301.      L0 := Label();
  302.      GetSym;
  303.      condition;
  304.      L1 := Label();
  305.      Gen(7,0,0);
  306.      IF sym=do THEN
  307.         GetSym;
  308.      ELSE
  309.         err(18);
  310.      END;
  311.      statement;
  312.      Gen(6,0,L0);
  313.      fixup(L1);
  314.   ELSIF sym=read THEN
  315.      GetSym;
  316.      IF sym=ident THEN
  317.         obj := find(id);
  318.         IF obj^.kind=Var THEN
  319.            Gen(1,0,14);
  320.            Gen(3,curlev-obj^.vlev,obj^.vadr);
  321.         ELSE
  322.            err(12);
  323.         END;
  324.      ELSE
  325.         err(14);
  326.      END;
  327.      GetSym;
  328.   ELSIF sym=write THEN
  329.      GetSym;
  330.      expression;
  331.      Gen(1,0,15);
  332.   END;
  333.   test(ident,19);
  334. END statement;
  335.  
  336.  
  337. PROCEDURE block;
  338. VAR
  339.   adr : CARDINAL;
  340.   L0 : CARDINAL;
  341.   hd, obj : ObjPtr;
  342.   
  343.   
  344.   PROCEDURE ConstDeclaration;
  345.   VAR
  346.     obj : ObjPtr;
  347.     
  348.   BEGIN
  349.     WriteString(win,"ConstDeclaration");
  350.     WriteLn(win);
  351.     IF sym=ident THEN
  352.        GetSym;
  353.        IF (sym=eql) OR (sym=becomes) THEN
  354.           IF sym=becomes THEN
  355.              err(1);
  356.           END;
  357.           GetSym;
  358.           IF sym=number THEN
  359.              obj := NewObj(Const);
  360.              obj^.val := num;
  361.              GetSym;
  362.           ELSE
  363.              err(2);
  364.           END;
  365.        ELSE
  366.           err(3);
  367.        END;
  368.     ELSE
  369.        err(4);
  370.     END;
  371.   END ConstDeclaration;
  372.   
  373.  
  374.   PROCEDURE VarDeclaration;
  375.   VAR
  376.     obj : ObjPtr;
  377.     
  378.   BEGIN
  379.     WriteString(win,"VarDeclaration");
  380.     WriteLn(win);
  381.     IF sym=ident THEN
  382.        obj := NewObj(Var);
  383.        GetSym;
  384.        obj^.vlev := curlev;
  385.        obj^.vadr := adr;
  386.        INC(adr);
  387.     ELSE
  388.        err(4);
  389.     END;
  390.   END VarDeclaration;
  391.   
  392.  
  393. BEGIN
  394.   WriteString(win,"block");
  395.   WriteLn(win);
  396.   INC(curlev);
  397.   adr := 3;
  398.   ALLOCATE(hd,TSIZE(Object));
  399.   WITH hd^ DO
  400.     kind := Header;
  401.     next := NIL;
  402.     last := hd;
  403.     name := 0;
  404.     down := topScope;
  405.   END;
  406.   topScope := hd;
  407.   L0 := Label();
  408.   Gen(6,0,0);
  409.   IF sym=const THEN
  410.      GetSym;
  411.      LOOP 
  412.        ConstDeclaration;
  413.        IF sym=comma THEN
  414.           GetSym;
  415.        ELSIF sym=semicolon THEN 
  416.           GetSym;
  417.           EXIT;
  418.        ELSIF sym=ident THEN
  419.           err(5);
  420.        ELSE
  421.           err(5);
  422.           EXIT;
  423.        END;
  424.      END;
  425.   END;
  426.   WHILE sym=procedure DO
  427.     GetSym;
  428.     IF sym=ident THEN
  429.        GetSym;
  430.     ELSE
  431.        err(4);
  432.     END;
  433.     obj := NewObj(Proc);
  434.     obj^.plev := curlev;
  435.     obj^.padr := Label();
  436.     IF sym=semicolon THEN
  437.        GetSym;
  438.     ELSE
  439.        err(5);
  440.     END;
  441.     block;
  442.     IF sym=semicolon THEN
  443.        GetSym;
  444.     ELSE
  445.        err(5);
  446.     END;
  447.   END;
  448.   fixup(L0);
  449.   Gen(5,0,adr);
  450.   statement;
  451.   Gen(1,0,0);
  452.   topScope := topScope^.down;
  453.   DEC(curlev);
  454. END block;
  455.  
  456.  
  457. PROCEDURE Parse;
  458. BEGIN
  459.   noerr := TRUE;
  460.   topScope := NIL;
  461.   curlev := 0;
  462.   Write(win,14C);
  463.   noerr := CreateHeap(100000,TRUE);
  464.   GetSym;
  465.   block;
  466.   IF sym # period THEN
  467.      err(9);
  468.   END;
  469. END Parse;
  470.  
  471.  
  472. PROCEDURE EndParser;
  473. BEGIN
  474.   CloseTextWindow(win);
  475. END EndParser;
  476.  
  477.  
  478. BEGIN
  479.   ALLOCATE(undef,TSIZE(Object));
  480.   ALLOCATE(bottom,0);
  481.   WITH undef^ DO
  482.     name := 0;
  483.     next := NIL;
  484.     kind := Var;
  485.     vlev := 0;
  486.     vadr := 0;
  487.   END; (* WITH *)
  488.   OpenTextWindow(win,WindowElements{Title},0,161,210,155,"PARSE");
  489. END PL0Parser.
  490.  
  491.  
  492.